package com.sinya.shoppingmall.https;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.StringRequest;
import com.google.gson.Gson;
import com.sinya.shoppingmall.MyApplication;
import com.sinya.shoppingmall.R;
import com.sinya.shoppingmall.bean.BaseResult;
import com.sinya.shoppingmall.bean.Constants;
import com.sinya.shoppingmall.utils.LogUtils;
import com.sinya.shoppingmall.widget.dialog.MyDialog;

import org.json.JSONArray;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 通用的请求Http类
 *
 * @author Koizumi Sinya on 2015/12/15.
 */
public class VolleyRequest {

    private static Context mContext;


    public static StringRequest stringRequest;

    private static List<String> tagList = new ArrayList<>();

    /**
     * 取消所有的Http请求
     */
    public static void CancelAll() {
        for (String tag : tagList) {
            Cancel(tag);
        }
    }

    /**
     * 根据tag 取消所有对应的Http请求
     *
     * @param tag
     */
    public static void Cancel(String tag) {
        if (tagList != null && tagList.size() > 0) {
            for (Iterator<String> iterator = tagList.iterator(); iterator.hasNext(); ) {
                String str = iterator.next();
                if (str.contains(tag)) {
                    iterator.remove();
                    LogUtils.I("Sinya", "关闭" + tag + "标签的请求");
                }
            }
        }
        MyApplication.getRequestQueue().cancelAll(tag);

    }

    /**
     * 中断请求
     */
    public static void Stop() {
        LogUtils.I("Sinya", "中断Volley连接");
        MyApplication.getRequestQueue().stop();
    }

    /**
     * 重新开启列队中的所有请求
     */
    public static void Again() {
        LogUtils.I("Sinya", "重启所有Volley中的请求列队");
        MyApplication.getRequestQueue().start();
    }

    /**
     * 开始网络请求数据
     *
     * @param handler
     * @param what
     * @param req
     * @param params
     */
    public static void Start(Context context, final Handler handler, final int what, final VolleyParams req, String... params) {
        mContext = context;

        Map<String, String> headerMap = new HashMap<>();
        Map<String, String> paramMap = new HashMap<>();

        if (params != null && params.length > 0) {
            //有请求头
            if (req.headerName != null && req.headerName.length > 0) {

                //先封装请求头
                for (int i = 0; i < req.headerName.length; i++) {
                    //LogUtils.I("Sinya", "封装请求头 HeaderMap" + i + "( " + req.headerName[i] + ", " + params[i] + " )");
                    headerMap.put(req.headerName[i], params[i]);
                }

                //封装请求参数
                for (int i = req.headerName.length; i < params.length; i++) {
                    //LogUtils.I("Sinya", "封装请求参数 ParamMap" + i + "( " + req.paramName[i - req.headerName.length] + ", " + params[i] + " )");
                    paramMap.put(req.paramName[i - req.headerName.length], params[i]);
                }

            } else {
                //无请求头，直接封装请求参数
                for (int i = 0; i < params.length; i++) {
                    //LogUtils.I("Sinya", "ParamMap" + i + "( " + req.paramName[i] + ", " + params[i] + " )");
                    paramMap.put(req.paramName[i], params[i]);
                }
            }
        }


        //TODO VolleyCallBack.mSuccessListener已经有实例化对象了么？逻辑代码？
        execute(new VolleyCallBack(req, headerMap, paramMap, VolleyCallBack.mSuccessListener, VolleyCallBack.mErrorListener) {
            @Override
            public void setSuccessResult(int statusCode, String result, String error) {
                LogUtils.I("Sinya", "statusCode: " + statusCode);
                LogUtils.I("Sinya", "result start\n" + result + "\nend");

                parseResult(new HttpVolleyResult(statusCode, result, error), handler, what);

            }

            @Override
            public void setErrorResult(int statusCode, String result, String error) {
                LogUtils.I("Sinya", "statusCode: " + statusCode + "\n" + error);
            }
        });

    }

    private static void execute(final VolleyCallBack volleyCallBack) {

        //拿到请求的params对象
        final VolleyParams req = volleyCallBack.req;
        //拿到对应的cmd请求关键字
        String url = Constants.BASE_URL + "/" + req.cmd;
        //将请求关键字设置为请求的唯一标识符
        String tag = req.cmd;
        //TODO 在开始新的请求前取消已发出的请求 不可以异步发出多次请求么？
        MyApplication.getRequestQueue().cancelAll(tag);

       //将发出的请求加入到历史集合管理中
        if (!tagList.contains(tag)) {
            LogUtils.I("Sinya", "加入" + tag + "标签");
            tagList.add(tag);
        }

        //在这里真正的发起请求
        stringRequest = new StringRequest(req.invokeMethod, url, volleyCallBack.getSuccessListener(), volleyCallBack.getErrorListener()) {

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {

                if (req.hadHeader) {
                    return volleyCallBack.headerMap;
                } else {
                    return super.getHeaders();
                }
            }

            @Override
            protected Map<String, String> getParams() throws AuthFailureError {

                if (req.hadParams) {
                    return volleyCallBack.paramMap;
                } else {
                    return super.getParams();
                }
            }

            @Override
            protected Response<String> parseNetworkResponse(NetworkResponse response) {

                //承接服务器返回的状态码
                volleyCallBack.statusCode = response.statusCode;
                try {

                    String resultFormat = new String(response.data, "UTF-8");
                    volleyCallBack.result = resultFormat;

                    return Response.success(resultFormat, HttpHeaderParser.parseCacheHeaders(response));

                } catch (Exception e) {
                    volleyCallBack.error = e.toString();
                    return Response.error(new ParseError(e));
                }
            }

            @Override
            protected VolleyError parseNetworkError(VolleyError volleyError) {

                if (volleyError.networkResponse != null && volleyError.networkResponse.data != null) {
                    volleyError = new VolleyError(volleyError.networkResponse);

                    try {
                        volleyCallBack.error = new String(volleyError.networkResponse.data, "UTF-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                        LogUtils.I("Sinya", e.toString());
                    }
                    volleyCallBack.statusCode = volleyError.networkResponse.statusCode;
                }

                return volleyError;
            }
        };


        //打上请求标签
        stringRequest.setTag(tag);
        //是否开启缓存
        stringRequest.setShouldCache(false);
        //设置请求超时时间
        stringRequest.setRetryPolicy(new DefaultRetryPolicy(8000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
        //加入Http请求队列中
        MyApplication.getRequestQueue().add(stringRequest);
    }

    //返回的数据是对象
    private static void parseResult(final HttpVolleyResult httpVolleyResult, final Handler handler, final int what) {

        final String result = httpVolleyResult.mResult;

        if (!TextUtils.isEmpty(result)) {
            Gson gson = new Gson();
            BaseResult bean = gson.fromJson(result, BaseResult.class);

            //TODO ！=0什么意思？
            if (bean.error_code != 0) {
                //TODO 根据错误码弹出错误信息
                showErrorDialog(bean.error_code);

            } else if (bean != null) {
                if (handler != null) {
                    Message msg = new Message();
                    msg.arg1 = httpVolleyResult.mStatusCode;
                    msg.what = what;
                    msg.obj = bean;
                    handler.sendMessage(msg);
                }
            } else {
                //TODO 弹出请求数据为空的信息
                showErrorDialog(2);
            }
        }
    }

    private static void showErrorDialog(int errorCode) {
        String showContent = mContext.getString(R.string.error_0001);

        switch (errorCode) {
            case Constants.ERROR_1530:
                showContent = mContext.getString(R.string.error_1530);
                break;
            case Constants.ERROR_1531:
                showContent = mContext.getString(R.string.error_1531);
                break;
            case Constants.ERROR_1532:
                showContent = mContext.getString(R.string.error_1532);
                break;
            case Constants.ERROR_1533:
                showContent = mContext.getString(R.string.error_1533);
                break;
            case Constants.ERROR_1534:
                showContent = mContext.getString(R.string.error_1534);
                break;
            case Constants.ERROR_1535:
                showContent = mContext.getString(R.string.error_1535);
                break;
            case Constants.ERROR_1536:
                showContent = mContext.getString(R.string.error_1536);
                break;
            case Constants.ERROR_1537:
                showContent = mContext.getString(R.string.error_1537);
                break;
            case Constants.ERROR_1538:
                showContent = mContext.getString(R.string.error_1538);
                break;
            case Constants.ERROR_0002:
                showContent = mContext.getString(R.string.error_0002);
                break;
            default:
                break;
        }

        MyDialog.showDialog(mContext, null, showContent, 1, true);
    }


    /**
     * @param result
     * @param classt
     * @param msg
     */
    public static Object transResult(String result, Class<?> classt, Message msg) {
        Gson gson = new Gson();
        try {
            List<Object> resultArray = new ArrayList<>();
            JSONArray jsonArray = new JSONArray(result);
            for (int i = 0; i < jsonArray.length(); i++) {
                resultArray.add(gson.fromJson(jsonArray.get(i).toString(), classt));
            }
            if (msg != null) msg.obj = resultArray;
            return resultArray;
        } catch (Exception e) {
            if (classt.equals(String.class)) return result;
            Object object = gson.fromJson(result, classt);
            if (msg != null) msg.obj = object;
            return object;
        }
    }


    // [+] 内部类

    static class HttpVolleyResult {
        public int mStatusCode;
        public String mResult;
        public String mError;

        public HttpVolleyResult(int statusCode, String result, String error) {
            mStatusCode = statusCode;
            mResult = result;
            mError = error;
        }
    }

    // [-] 内部类

}
